﻿/**	align.hpp
 *	----	Create Time Stamp	--2005-09-17 03:04:26--
 *-----------------------------------------------------------------------------
 *	Mean	:结构对齐相关
 *	Author	:Nick Shallery	(nicknide@gmail.com)
 *	Version	:1.0.21.27		(2009-09-26 22:07:04)
 *-----------------------------------------------------------------------------
**/	/*YOU HAVE ALL LEFT WITH THIS CODE WHILE YOU KEEP COMMENT IN EVERY COPY.*/


#if			!defined(__LOLIX__TOY__ALIGN__HPP__NICK__K_IN_G__)
#define		__LOLIX__TOY__ALIGN__HPP__NICK__K_IN_G__

#if			!defined(__LOLIX__LOLI_X_MACRO__K_IN_G__)
	#include	"../lolix_macro.h"
#endif	//	!defined(__LOLIX__LOLI_X_MACRO__K_IN_G__)

#if			!defined(__LOLIX__TOY__L_X_ASSERT_NICK__K_IN_G__)
	#include	"./lx_assert.h"
#endif	//	!defined(__LOLIX__TOY__L_X_ASSERT_NICK__K_IN_G__)

#if			!defined(__LOLIX__TOY__REBIND_TYPE__K_IN_G__)
	#include	"./rebind_type.hpp"
#endif	//	!defined(__LOLIX__TOY__REBIND_TYPE__K_IN_G__)

#if			defined(__cplusplus)
namespace	lolix{namespace toy{
	template<unsigned long long _V_sz>	class log_2;

	template <unsigned int base, unsigned int now>	class	high_align;
	template <unsigned int base, unsigned int now>	class	low_align;
	//	类型对齐， 按照 1, 2, 4, 8 递增, 最多到 8
	template <unsigned long long input_size>	class type_align;
	//	填充结构到按照某个大小对齐
	template<typename base_type, unsigned long long align_size>	class fill_space_to_align;
	template<unsigned long long input_val>	class size_info;
	template<typename _Ty> _Ty get_1cnt_by_val(_Ty val);

	namespace _help{
		template<typename base_type, unsigned long long size, bool fill = true>	class fill_space;
		template<unsigned long long sz>	class LESS_BITS;
		template<typename SIZE_L, typename SIZE_R>	struct PAIR_SIZE;
		template<typename _Ty>
		class	__value_to_pow;
	}
}}


template<unsigned long long _V_sz>
class lolix::toy::log_2
{
public:
	enum { value = log_2<_V_sz/2>::value + 1 };
};


template<>
class lolix::toy::log_2<1>
{
public:
	enum { value = 0 };
};


template<>
class lolix::toy::log_2<0>
{
};


//	------------------------------------------------------------------->
//	填充结构大小
#ifdef		_MSC_VER
#	pragma pack(push,1)
#endif	//	_MSC_VER
template<typename base_type, unsigned long long size, bool fill>
class lolix::toy::_help::fill_space: public base_type
{
	typedef fill_space<base_type, size, fill>	this_type;
private:
	char dont_touch_me[size];
	//STATIC_ASSERT(sizeof(this_type) - sizeof(base_type) == size);
};

template<typename base_type, unsigned long long size>
class lolix::toy::_help::fill_space<base_type, size, false>: public base_type
{
	typedef	fill_space<base_type, size, false>	this_type;
	STATIC_ASSERT(sizeof(this_type) - sizeof(base_type) == 0);
};
template<typename base_type>
class lolix::toy::_help::fill_space<base_type, 0, true>: public base_type
{
	typedef fill_space<base_type, 0, true> this_type;
	STATIC_ASSERT(sizeof(this_type) - sizeof(base_type) == 0);
};
template<typename base_type>
class lolix::toy::_help::fill_space<base_type, 0, false>: public base_type
{
	typedef fill_space<base_type, 0, false>	this_type;
	STATIC_ASSERT(sizeof(this_type) - sizeof(base_type) == 0);
};

#ifdef		_MSC_VER
#	pragma pack(pop)
#endif	//	_MSC_VER

//	<-------------------------------------------------------------------
//	<-------------------------------------------------------------------
//	向上，和向下对齐数据
template <unsigned int base, unsigned int now>
class	lolix::toy::high_align
{
public:
	enum {align_value = (now/base)*base + (now%base?base:0)};
};

template <unsigned int base, unsigned int now>
class	lolix::toy::low_align
{
public:
	enum {align_value = (now/base)*base};
};

//	类型对齐， 按照 1, 2, 4, 8 递增, 最多到 8
template <unsigned long long input_size>
class lolix::toy::type_align
{
	template<unsigned int v, unsigned long long ipt_size>
	struct _h_align
	{
		enum { value = ((ipt_size>>(8*v)) == 0)? v: _h_align<2*v, ipt_size>::value };
	};

	//	只要到了 8, 就自然封顶
	template<unsigned long long in_size>
	struct _h_align<8, in_size>
	{
		enum { value = 8 };
	};

	STATIC_ASSERT( (_h_align<1, 0x00000000000000ff>::value == 1) );
	STATIC_ASSERT( (_h_align<1, 0x000000000000ffff>::value == 2) );
	STATIC_ASSERT( (_h_align<1, 0x00000000ffffffff>::value == 4) );
	STATIC_ASSERT( (_h_align<1, 0xffffffffffffffff>::value == 8) );
public:
	enum {value = _h_align<1, input_size>::value};
};
//	------------------------------------------------------------------->


//	<-------------------------------------------------------------------
//	填充结构到按照某个大小对齐
template<typename base_type, unsigned long long align_size>
class lolix::toy::fill_space_to_align
	: public _help::fill_space
	<
	base_type,
	high_align<align_size, sizeof(base_type)>::align_value - sizeof(base_type),
	(high_align<align_size, sizeof(base_type)>::align_value > sizeof(base_type))
		>
{ };
//	------------------------------------------------------------------->


template<unsigned long long sz>
class lolix::toy::_help::LESS_BITS
{
public:
	enum { SIZE = LESS_BITS<(sz>>1)>::SIZE+1 };
};
template<>
class lolix::toy::_help::LESS_BITS<0>
{
public:
	enum { SIZE = 0 };
};
template<typename SIZE_L, typename SIZE_R>
struct lolix::toy::_help::PAIR_SIZE
{
	template<bool f, SIZE_L L, SIZE_R R>
	struct CHOICE_TYPE
	{
		static const SIZE_L size_value = L;
	};

	template<SIZE_L L, SIZE_R R>
	struct CHOICE_TYPE<false, L, R>
	{
		static const SIZE_R size_value = R;
	};
};


template<typename _Ty>
class	lolix::toy::_help::__value_to_pow
{
	LOLIX_INLINE_CALL	static	_Ty __pow(_Ty c)
	{
		return static_cast<type>(1) << c;
	}

	LOLIX_INLINE_CALL	static	_Ty __mask(_Ty c)
	{
		_Ty val = c;
		val = __pow(val);
		val = __pow(val);
		val = static_cast<_Ty>(-1)/val;
		return ++val;
	}

	LOLIX_INLINE_CALL	static	_Ty __round(_Ty n, _Ty cnt)
	{
		_Ty m = __mask(cnt);
		return (val & m) + ((n >> __pow(cnt)) & m);
	}
public:

	LOLIX_INLINE_CALL	static	_Ty value(_Ty v)
	{
		_Ty i = -1;
		switch ( sizeof(_Ty) )
		{
		case 16:
			v = __rounc(v, ++i);
		case 8:
			v = __rounc(v, ++i);
		case 4:
			v = __rounc(v, ++i);
		case 2:
			v = __rounc(v, ++i);
		case 1:
			v = __rounc(v, ++i);
		}
		v = __rounc(v, ++i);
		v = __rounc(v, ++i);
		return v;
	}
};



template<typename _Ty>
_Ty		lolix::toy::get_1cnt_by_val(_Ty val)
{
	return _help::__value_to_pow::value(val);
}


#define		static_min(l, r)		(lolix::toy::_help::PAIR_SIZE<REBIND_TYPE(l), REBIND_TYPE(r)>::CHOICE_TYPE<(l<=r), l, r>::size_value)
#define		static_max(l, r)		(lolix::toy::_help::PAIR_SIZE<REBIND_TYPE(l), REBIND_TYPE(r)>::CHOICE_TYPE<(l>=r), l, r>::size_value)
#define		static_clamp(ipt,l,h)	static_min(static_max(ipt,l),h)

#define		less_bits(sz)			lolix::toy::_help::LESS_BITS<sz>::SIZE

#define		HIGH_ALIGN(base, want)	(lolix::toy::high_align<(base),(want)>::align_value)
#define		LOW_ALIGN(base, want)	(lolix::toy::low_align<(base),(want)>::align_value)

template<unsigned long long input_val>
class lolix::toy::size_info
{
	template<typename gcc_only, unsigned int offset_size>class size_bind_type{public:typedef void	difference_type;};
	template<typename gcc_only>class size_bind_type<gcc_only, 1>{public: typedef char		difference_type;	typedef unsigned char		size_type;};
	template<typename gcc_only>class size_bind_type<gcc_only, 2>{public: typedef short		difference_type;	typedef unsigned short		size_type;};
	template<typename gcc_only>class size_bind_type<gcc_only, 4>{public: typedef int		difference_type;	typedef	unsigned int		size_type;};
	template<typename gcc_only>class size_bind_type<gcc_only, 8>{public: typedef long long	difference_type;	typedef	unsigned long long	size_type;};
public:
	enum { size_bits = less_bits(input_val) };			//	字位数
	enum { size_byte = (less_bits(input_val) + 7)/8 };	//	字节数
	enum { size_std = lolix::toy::type_align<input_val>::value };	//	按照系统以及编译器的2次方对齐数
	typedef typename size_bind_type<void, size_std>::difference_type	difference_type;
	typedef typename size_bind_type<void, size_std>::size_type			size_type;
};


namespace lolix{namespace _help{
	//	why we need this _NoUsed here, see below LOLIX_DOWN_ALIGN_TO
template<typename _Ty, size_t _NoUsed>
struct	get_as_val
{
	static LOLIX_INLINE_CALL	_Ty		val(_Ty val)
	{
		return val;
	}
};

template<typename _Ty, size_t _NoUsed>
struct	get_as_val<_Ty*, _NoUsed>
{
	static LOLIX_INLINE_CALL	size_t		val(_Ty* val)
	{
		return (size_t)val;
	}
};

//template<typename _Ty>	LOLIX_INLINE_CALL	size_t	get_as_val(_Ty* val){ return (size_t)val; }
template<typename _Ti, typename _To>	LOLIX_INLINE_CALL	_To	get_as_out(_Ti i, _To){ return (_To)i; }
template<typename _Ty>
class	any_cast
{
	template<typename _To, typename Ti>
	LOLIX_INLINE_CALL	static	_To _cast_val(Ti val)
	{
		return (_To)val;
	}
public:
	_Ty _val;
	LOLIX_INLINE_CALL	any_cast<_Ty>(_Ty v):_val(v){}
	template<typename _To>
	LOLIX_INLINE_CALL	any_cast<_Ty>(any_cast<_To> o): _val(_cast_val<_Ty, _To>(o._val)){}
	template<typename _To>
	LOLIX_INLINE_CALL	any_cast<_Ty>(_To o): _val(_cast_val<_Ty, _To>(o)){}

	template<typename _To>
	LOLIX_INLINE_CALL	operator _To(void)const
	{
		return _cast_val<_To, _Ty>(_val);
	}
#define		__LOLIX_DEF__OPT__(opt)	template<typename _To>	bool operator opt(const _To o){ return (_To)_val opt o;}
__LOLIX_DEF__OPT__(==);
__LOLIX_DEF__OPT__(<);
__LOLIX_DEF__OPT__(<=);
__LOLIX_DEF__OPT__(>);
__LOLIX_DEF__OPT__(>=);
__LOLIX_DEF__OPT__(!=);
#undef	__LOLIX_DEF__OPT__
};

//#define		__LOLIX_DEF__OPT__(opt)	template<typename _To, typename _Ta>	bool operator opt(const _To o, _Ta a){ return o opt (_To)a;}
//__LOLIX_DEF__OPT__(==);
//__LOLIX_DEF__OPT__(<);
//__LOLIX_DEF__OPT__(<=);
//__LOLIX_DEF__OPT__(>);
//__LOLIX_DEF__OPT__(>=);
//__LOLIX_DEF__OPT__(!=);
//#undef	__LOLIX_DEF__OPT__

}}

template<typename _Tt, typename _Tb>
LOLIX_INLINE_CALL	lolix::_help::any_cast<_Tt>	LOLIX_DOWN_ALIGN_TO(_Tt tgr, _Tb b)
	{
	using namespace lolix::_help;
	//	当某些编译器（比如 VS 2005) 特化下面的同型模版的时候， 如果特化出来的模版已经
	//	能够支持另一处的使用， 则不会继续特化第二个模版， 因此使用序号强制特化出不同的实例
	//	出来
	return any_cast<_Tt>(get_as_val<_Tt, 0>::val(tgr)&(~(get_as_val<_Tb, 1>::val(b)-1)));
	}


template<typename _Tt, typename _Tb>
LOLIX_INLINE_CALL	lolix::_help::any_cast<_Tt>	LOLIX_UP_ALIGN_TO(_Tt tgr, _Tb b)
	{
	using namespace lolix::_help;
	return LOLIX_DOWN_ALIGN_TO(get_as_val<_Tt, 0>::val(tgr) + get_as_val<_Tb, 1>::val(b)-1, b);
	}

template<typename _Tt, typename _Tb>
LOLIX_INLINE_CALL	lolix::_help::any_cast<_Tt>	LOLIX_DOWN_POWER_TO(_Tt tgr, _Tb b)
	{
	using namespace lolix::_help;
	_Tb v(b), l(b);
	while( get_as_val<_Tt, 0>::val(tgr) > get_as_val<_Tb, 1>::val(v) )
		{
		l = v;
		v *= b;
		}
	return any_cast<_Tt>(l);
	}


template<typename _Tt, typename _Tb>
LOLIX_INLINE_CALL	lolix::_help::any_cast<_Tt>	LOLIX_UP_POWER_TO(_Tt tgr, _Tb b)
	{
	using namespace lolix::_help;
	_Tb v(b);
	while( get_as_val<_Tt, 0>::val(tgr) > get_as_val<_Tb, 1>::val(v) )
		v *= b;
	return any_cast<_Tt>(v);
	}

#endif	//	defined(__cplusplus)

#define		FILL_BITS(type, from, end)	( ((type)1<<(end)) - ((type)1<<(from)) )



#endif	//	!defined(__LOLIX__TOY__ALIGN__HPP__NICK__K_IN_G__)
